// QtMyBatisPlus.cpp
#include "qtmybatisplus.h"
#include <QTimer>
namespace QtMyBatisPlus {



/********************* QueryWrapper 实现 *********************/
QueryWrapper::QueryWrapper()
    : m_offset(0), m_limit(0) {}

QueryWrapper& QueryWrapper::eq(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, "=", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::ne(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, "<>", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::gt(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, ">", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::ge(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, ">=", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::lt(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, "<", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::le(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, "<=", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::between(const QString& column, const QVariant& low, const QVariant& high) {
    if (low.isValid() && high.isValid()) {
        QString param = sanitizeKey(column);
        m_conditions.append(QString("%1 BETWEEN :%2_low AND :%2_high").arg(column).arg(param));
        m_params.insert(param + "_low", low);
        m_params.insert(param + "_high", high);
    }
    return *this;
}

QueryWrapper& QueryWrapper::notBetween(const QString& column, const QVariant& low, const QVariant& high) {
    if (low.isValid() && high.isValid()) {
        QString param = sanitizeKey(column);
        m_conditions.append(QString("%1 NOT BETWEEN :%2_low AND :%2_high").arg(column).arg(param));
        m_params.insert(param + "_low", low);
        m_params.insert(param + "_high", high);
    }
    return *this;
}

QueryWrapper& QueryWrapper::in(const QString& column, const QVariantList& values) {
    if (!values.isEmpty()) {
        QStringList placeholders;
        QString paramBase = sanitizeKey(column);
        for (int i = 0; i < values.size(); ++i) {
            QString param = paramBase + "_in_" + QString::number(i);
            placeholders.append(":" + param);
            m_params.insert(param, values[i]);
        }
        m_conditions.append(QString("%1 IN (%2)").arg(column).arg(placeholders.join(", ")));
    }
    return *this;
}

QueryWrapper& QueryWrapper::notIn(const QString& column, const QVariantList& values) {
    if (!values.isEmpty()) {
        QStringList placeholders;
        QString paramBase = sanitizeKey(column);
        for (int i = 0; i < values.size(); ++i) {
            QString param = paramBase + "_in_" + QString::number(i);
            placeholders.append(":" + param);
            m_params.insert(param, values[i]);
        }
        m_conditions.append(QString("%1 NOT IN (%2)").arg(column).arg(placeholders.join(", ")));
    }
    return *this;
}

QueryWrapper& QueryWrapper::like(const QString& column, const QString& value) {
    if (!value.isEmpty()) {
        addCondition(column, "LIKE", QVariant("%" + value + "%"));
    }
    return *this;
}

QueryWrapper& QueryWrapper::notLike(const QString& column, const QString& value) {
    if (!value.isEmpty()) {
        addCondition(column, "NOT LIKE", QVariant("%" + value + "%"));
    }
    return *this;
}

QueryWrapper& QueryWrapper::startsWith(const QString& column, const QString& value) {
    if (!value.isEmpty()) {
        addCondition(column, "LIKE", QVariant(value + "%"));
    }
    return *this;
}

QueryWrapper& QueryWrapper::endsWith(const QString& column, const QString& value) {
    if (!value.isEmpty()) {
        addCondition(column, "LIKE", QVariant("%" + value));
    }
    return *this;
}

QueryWrapper& QueryWrapper::isNull(const QString& column) {
    m_conditions.append(QString("%1 IS NULL").arg(column));
    return *this;
}

QueryWrapper& QueryWrapper::isNotNull(const QString& column) {
    m_conditions.append(QString("%1 IS NOT NULL").arg(column));
    return *this;
}

QueryWrapper& QueryWrapper::orCondition(const QueryWrapper& other) {
    if (!other.m_conditions.isEmpty()) {
        m_orConditions.append(other);
    }
    return *this;
}

QueryWrapper& QueryWrapper::orNew(const QueryWrapper& other) {
    return orCondition(other);
}

QueryWrapper& QueryWrapper::notCondition(const QueryWrapper& other) {
    if (!other.m_conditions.isEmpty()) {
        QString whereClause = other.buildWhereClause();
        if (whereClause.startsWith("WHERE ")) {
            whereClause = whereClause.mid(6);
        }
        m_conditions.append("NOT (" + whereClause + ")");

        // 合并参数
        QVariantMap otherParams = other.allParams();
        for (auto it = otherParams.constBegin(); it != otherParams.constEnd(); ++it) {
            m_params.insert(it.key(), it.value());
        }
    }
    return *this;
}

QueryWrapper& QueryWrapper::orderByAsc(const QString& column) {
    m_orderBy = QString("ORDER BY %1 ASC").arg(column);
    return *this;
}

QueryWrapper& QueryWrapper::orderByDesc(const QString& column) {
    m_orderBy = QString("ORDER BY %1 DESC").arg(column);
    return *this;
}

QueryWrapper& QueryWrapper::groupBy(const QString& column) {
    m_groupBy = QString("GROUP BY %1").arg(column);
    return *this;
}

QueryWrapper& QueryWrapper::page(int pageNum, int pageSize) {
    m_offset = (pageNum - 1) * pageSize;
    m_limit = pageSize;
    return *this;
}

QString QueryWrapper::buildWhereClause() const {
    QStringList allConditions = m_conditions;

    for (const auto& orWrapper : m_orConditions) {
        QString orClause = orWrapper.buildWhereClause();
        if (!orClause.isEmpty()) {
            if (orClause.startsWith("WHERE ")) {
                orClause = orClause.mid(6);
            }
            allConditions.append("(" + orClause + ")");
        }
    }

    if (allConditions.isEmpty()) return "";
    return "WHERE " + allConditions.join(" AND ");
}

QString QueryWrapper::buildSqlClause() const {
    QString sql;

    QString whereClause = buildWhereClause();
    if (!whereClause.isEmpty()) {
        sql += " " + whereClause;
    }

    if (!m_groupBy.isEmpty()) {
        sql += " " + m_groupBy;
    }

    if (!m_orderBy.isEmpty()) {
        sql += " " + m_orderBy;
    }

    if (m_limit > 0) {
        sql += QString(" OFFSET %1 ROWS FETCH NEXT %2 ROWS ONLY").arg(m_offset).arg(m_limit);
    }

    return sql;
}

QVariantMap QueryWrapper::allParams() const {
    QList<QVariantMap> allParamMaps;
    allParamMaps.append(m_params);

    for (const auto& orWrapper : m_orConditions) {
        allParamMaps.append(orWrapper.allParams());
    }

    return QVariantUtils::safeMerge(allParamMaps);
}

void QueryWrapper::addExtraParam(const QString& key, const QVariant& value) {
    m_extraParams.insert(key, value);
}

QVariantMap QueryWrapper::allParamsWithExtra() const {
    QVariantMap params = allParams();
    for (auto it = m_extraParams.constBegin(); it != m_extraParams.constEnd(); ++it) {
        params.insert(it.key(), it.value());
    }
    return params;
}

void QueryWrapper::addCondition(const QString& column, const QString& op, const QVariant& value) {
    QString param = sanitizeKey(column);
    m_conditions.append(QString("%1 %2 :%3").arg(column).arg(op).arg(param));
    m_params.insert(param, value);
}

QString QueryWrapper::sanitizeKey(const QString& key) const {
    QString keyTmp = key ;
    keyTmp.replace('.', '_').replace(' ', '_').replace('(', '_').replace(')', '_');
    return keyTmp ;
}

/********************* BaseMapper 实现 *********************/
template<typename T>
BaseMapper<T>::BaseMapper() {
    m_connection = ConnectionPool::instance().getConnection();
}

template<typename T>
BaseMapper<T>::~BaseMapper() {
    ConnectionPool::instance().releaseConnection(m_connection);
}

template<typename T>
bool BaseMapper<T>::insert(T& entity) {
    // 自动填充创建时间和更新时间
    auto now = QDateTime::currentDateTime();
    if constexpr (has_create_time<T>::value) {
        entity.createdAt = now;
    }
    if constexpr (has_update_time<T>::value) {
        entity.updatedAt = now;
    }

    QSqlQuery query(m_connection);
    QString sql = buildInsertSql();

    if (!query.prepare(sql)) {
        qWarning() << "Prepare insert SQL failed:" << query.lastError().text();
        return false;
    }

    bindInsertParams(query, entity);

    if (!query.exec()) {
        handleQueryError(query);
        return false;
    }

    // 获取自增ID
    if (T::isId() && T::isAutoIncrement()) {
        QVariant id = query.lastInsertId();
        if (id.isValid()) {
            entity.id = id.toInt();
        }
    }

    return true;
}

template<typename T>
bool BaseMapper<T>::updateById(T& entity) {
    // 自动填充更新时间
    if constexpr (has_update_time<T>::value) {
        entity.updatedAt = QDateTime::currentDateTime();
    }

    QSqlQuery query(m_connection);
    QString sql = buildUpdateSql();

    if (!query.prepare(sql)) {
        qWarning() << "Prepare update SQL failed:" << query.lastError().text();
        return false;
    }

    bindUpdateParams(query, entity);

    if (!query.exec()) {
        handleQueryError(query);
        return false;
    }

    return query.numRowsAffected() > 0;
}

template<typename T>
bool BaseMapper<T>::deleteById(int id) {
    QSqlQuery query(m_connection);
    QString sql = QString("DELETE FROM %1 WHERE id = :id").arg(T::tableName());

    if (!query.prepare(sql)) {
        qWarning() << "Prepare delete SQL failed:" << query.lastError().text();
        return false;
    }

    query.bindValue(":id", id);

    if (!query.exec()) {
        handleQueryError(query);
        return false;
    }

    return query.numRowsAffected() > 0;
}

template<typename T>
T BaseMapper<T>::selectById(int id) {
    QueryWrapper wrapper;
    wrapper.eq("id", id);
    QList<T> result = selectList(wrapper);
    return result.isEmpty() ? T() : result.first();
}

template<typename T>
QList<T> BaseMapper<T>::selectList(const QueryWrapper& wrapper) {
    QList<T> result;
    QSqlQuery query(m_connection);

    QString sql = QString("SELECT * FROM %1 %2")
                      .arg(T::tableName())
                      .arg(wrapper.buildSqlClause());

    if (!query.prepare(sql)) {
        qWarning() << "Prepare select SQL failed:" << query.lastError().text();
        return result;
    }

    // 使用合并后的所有参数
    QVariantMap params = wrapper.allParamsWithExtra();
    bindParams(query, params);

    if (!query.exec()) {
        handleQueryError(query);
        return result;
    }

    while (query.next()) {
        result.append(extractEntity(query));
    }

    return result;
}

template<typename T>
T BaseMapper<T>::selectOne(const QueryWrapper& wrapper) {
    QueryWrapper limitedWrapper = wrapper;
    limitedWrapper.page(1, 1);
    QList<T> result = selectList(limitedWrapper);
    return result.isEmpty() ? T() : result.first();
}

template<typename T>
int BaseMapper<T>::selectCount(const QueryWrapper& wrapper) {
    QSqlQuery query(m_connection);

    QString sql = QString("SELECT COUNT(*) FROM %1 %2")
                      .arg(T::tableName())
                      .arg(wrapper.buildWhereClause());

    if (!query.prepare(sql)) {
        qWarning() << "Prepare count SQL failed:" << query.lastError().text();
        return -1;
    }

    // 使用合并后的所有参数
    QVariantMap params = wrapper.allParamsWithExtra();
    bindParams(query, params);

    if (!query.exec() || !query.next()) {
        handleQueryError(query);
        return -1;
    }

    return query.value(0).toInt();
}

template<typename T>
bool BaseMapper<T>::exists(const QueryWrapper& wrapper) {
    return selectCount(wrapper) > 0;
}


template<typename T>
QString BaseMapper<T>::buildInsertSql() {
    QStringList columns;
    QStringList placeholders;

    // 自增字段在插入时不包含
    if constexpr (!T::isAutoIncrement()) {
        if constexpr (std::is_same_v<decltype(T::id), int>) {
            columns << "id";
            placeholders << ":id";
        }
    }

    // 根据实体字段动态构建
    if constexpr (std::is_same_v<decltype(T::name), QString>) {
        columns << "name";
        placeholders << ":name";
    }
    if constexpr (std::is_same_v<decltype(T::email), QString>) {
        columns << "email";
        placeholders << ":email";
    }
    if constexpr (std::is_same_v<decltype(T::age), int>) {
        columns << "age";
        placeholders << ":age";
    }
    if constexpr (std::is_same_v<decltype(T::createdAt), QDateTime>) {
        columns << "created_at";
        placeholders << ":created_at";
    }
    if constexpr (std::is_same_v<decltype(T::updatedAt), QDateTime>) {
        columns << "updated_at";
        placeholders << ":updated_at";
    }

    return QString("INSERT INTO %1 (%2) VALUES (%3)")
        .arg(T::tableName())
        .arg(columns.join(", "))
        .arg(placeholders.join(", "));
}

template<typename T>
void BaseMapper<T>::bindInsertParams(QSqlQuery& query, T& entity) {
    // 自增字段在插入时不绑定
    if constexpr (!T::isAutoIncrement()) {
        if constexpr (std::is_same_v<decltype(T::id), int>) {
            query.bindValue(":id", entity.id);
        }
    }

    // 根据实体字段动态绑定
    if constexpr (std::is_same_v<decltype(T::name), QString>) {
        query.bindValue(":name", entity.name);
    }
    if constexpr (std::is_same_v<decltype(T::email), QString>) {
        query.bindValue(":email", entity.email);
    }
    if constexpr (std::is_same_v<decltype(T::age), int>) {
        query.bindValue(":age", entity.age);
    }
    if constexpr (std::is_same_v<decltype(T::createdAt), QDateTime>) {
        query.bindValue(":created_at", entity.createdAt);
    }
    if constexpr (std::is_same_v<decltype(T::updatedAt), QDateTime>) {
        query.bindValue(":updated_at", entity.updatedAt);
    }
}

template<typename T>
QString BaseMapper<T>::buildUpdateSql() {
    QStringList sets;

    // 根据实体字段动态构建
    if constexpr (std::is_same_v<decltype(T::name), QString>) {
        sets << "name = :name";
    }
    if constexpr (std::is_same_v<decltype(T::email), QString>) {
        sets << "email = :email";
    }
    if constexpr (std::is_same_v<decltype(T::age), int>) {
        sets << "age = :age";
    }
    if constexpr (std::is_same_v<decltype(T::updatedAt), QDateTime>) {
        sets << "updated_at = :updated_at";
    }

    return QString("UPDATE %1 SET %2 WHERE id = :id")
        .arg(T::tableName())
        .arg(sets.join(", "));
}

template<typename T>
void BaseMapper<T>::bindUpdateParams(QSqlQuery& query, T& entity) {
    if constexpr (std::is_same_v<decltype(T::id), int>) {
        query.bindValue(":id", entity.id);
    }
    if constexpr (std::is_same_v<decltype(T::name), QString>) {
        query.bindValue(":name", entity.name);
    }
    if constexpr (std::is_same_v<decltype(T::email), QString>) {
        query.bindValue(":email", entity.email);
    }
    if constexpr (std::is_same_v<decltype(T::age), int>) {
        query.bindValue(":age", entity.age);
    }
    if constexpr (std::is_same_v<decltype(T::updatedAt), QDateTime>) {
        query.bindValue(":updated_at", entity.updatedAt);
    }
}

template<typename T>
T BaseMapper<T>::extractEntity(const QSqlQuery& query) {
    T entity;

    // 根据实体字段动态提取
    if constexpr (std::is_same_v<decltype(T::id), int>) {
        entity.id = query.value("id").toInt();
    }
    if constexpr (std::is_same_v<decltype(T::name), QString>) {
        entity.name = query.value("name").toString();
    }
    if constexpr (std::is_same_v<decltype(T::email), QString>) {
        entity.email = query.value("email").toString();
    }
    if constexpr (std::is_same_v<decltype(T::age), int>) {
        entity.age = query.value("age").toInt();
    }
    if constexpr (std::is_same_v<decltype(T::createdAt), QDateTime>) {
        entity.createdAt = query.value("created_at").toDateTime();
    }
    if constexpr (std::is_same_v<decltype(T::updatedAt), QDateTime>) {
        entity.updatedAt = query.value("updated_at").toDateTime();
    }

    return entity;
}

template<typename T>
void BaseMapper<T>::bindParams(QSqlQuery& query, const QVariantMap& params) {
    for (auto it = params.constBegin(); it != params.constEnd(); ++it) {
        QString placeholder = ":" + it.key();

        // 检查占位符是否在SQL语句中
        if (query.lastQuery().contains(placeholder)) {
            query.bindValue(placeholder, it.value());
        }
        // 处理其他格式的占位符
        else if (query.lastQuery().contains("#{" + it.key() + "}")) {
            query.bindValue("#{" + it.key() + "}", it.value());
        }
    }
}

template<typename T>
void BaseMapper<T>::handleQueryError(const QSqlQuery& query) {
    QString errorMsg = query.lastError().text();
    QString executedSql = query.executedQuery();

    qWarning() << "SQL execution error:" << errorMsg;
    qWarning() << "Executed SQL:" << executedSql;
    qWarning() << "Bound values:" << query.boundValues();
}

} // namespace QtMyBatisPlus

